package com.example.provider.qiniuyun;

import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FetchRet;
import com.qiniu.storage.persistent.FileRecorder;
import com.qiniu.util.Auth;
import com.qiniu.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * All rights Reserved, Designed By www.maihaoche.com
 *
 * @Package com.example.provider.qiniuyun
 * @author: 红雪（hongxue@maihaoche.com）
 * @date: 2019/1/28 4:07 PM
 * @Copyright: 2017-2020 www.maihaoche.com Inc. All rights reserved.
 * 注意：本内容仅限于卖好车内部传阅，禁止外泄以及用于其他的商业项目
 */
@Slf4j
public class QiniuServiceImpl extends AbstractQiniuUpload {

    private final String accessKey;
    private final String secretKey;
    private final String bucket;
    private final String domain;
    private final boolean isOpen;
    private final Zone zone;


    private final Auth auth;
    private final Configuration cfg;
    private final UploadManager uploadManager;

    public QiniuServiceImpl(QiniuBase qiniuBase) {
        super(qiniuBase);
        accessKey = qiniuBase.accessKey();
        secretKey = qiniuBase.secretKey();
        bucket = qiniuBase.openBucket();
        domain = programDomain(qiniuBase.domain());
        isOpen = qiniuBase.isOpen();
        zone = qiniuBase.zone();
        cfg = new Configuration(zone);
        uploadManager = new UploadManager(cfg);
        auth= Auth.create(accessKey, secretKey);
    }


    @Override
    public APIResult<String> upload(File file) {

        if (file==null){
            log.info("file不能为null");
            return APIResult.create(ErrorCodeEnum.NOT_NULL);
        }
        //处理文件命名
        String fileName = file.getName();
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        String key = UUID.randomUUID().toString().toUpperCase() + suffix;

        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(file.getAbsolutePath(), key, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            log.info("上传成功，本地文件名:{}，返回信息:{}", fileName, domain + putRet.key);
            return APIResult.create(domain + putRet.key);
        } catch (QiniuException ex) {
            Response r = ex.response;
            log.info("上传失败，错误信息:{}", r.toString());
            return APIResult.create(Integer.toString(r.statusCode), r.toString());
        }
    }

    @Override
    public APIResult<String> upload(File file, String fileName) {

        if (file==null){
            log.info("file不能为null");
            APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        if (StringUtils.isNullOrEmpty(fileName)){
            log.info("fileName不能为空");
            APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(file.getAbsolutePath(), fileName, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            log.info("上传成功，本地文件名:{}，返回信息:{}", fileName, domain + putRet.key);
            return APIResult.create(domain + putRet.key);
        } catch (QiniuException ex) {
            Response r = ex.response;
            log.info("上传失败，错误信息:{}", r.toString());
            return APIResult.create(Integer.toString(r.statusCode), r.toString());
        }
    }



    @Override
    public APIResult<String> upload(byte[] fileBytes, String fileName) {

        if (fileBytes==null){
            log.info("fileBytes不能为null");
            return  APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        if (StringUtils.isNullOrEmpty(fileName)){
            log.info("fileName不能为空");
            return  APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(fileBytes, fileName, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            log.info("上传成功，本地文件名:{}，返回信息:{}", fileName, domain + putRet.key);
            return APIResult.create(domain + putRet.key);
        } catch (QiniuException ex) {
            Response r = ex.response;
            log.info("上传失败，错误信息:{}", r.toString());
            return APIResult.create(Integer.toString(r.statusCode), r.toString());
        }
    }

    @Override
    public APIResult<String> uploadResume(File file)  {

        if (file==null){
            log.info("file不能为null");
            return APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        //处理文件命名
        String fileName = file.getName();
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        String key = UUID.randomUUID().toString().toUpperCase() + suffix;

        String upToken = auth.uploadToken(bucket);
        String localTempDir = Paths.get(file.getParent(), bucket).toString();
        System.out.println(localTempDir);
        try {
            //设置断点续传文件进度保存目录
            FileRecorder fileRecorder = new FileRecorder(localTempDir);
            UploadManager uploadManager = new UploadManager(cfg, fileRecorder);
            Response response = uploadManager.put(file.getAbsolutePath(), key, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            log.info("上传成功，本地文件名:{}，返回信息:{}", fileName, domain + putRet.key);
            return APIResult.create(domain + putRet.key);
        } catch (QiniuException ex) {
            Response r = ex.response;
            log.info("上传失败，错误信息:{}", r.toString());
            return APIResult.create(Integer.toString(r.statusCode), r.toString());
        } catch (IOException e) {
            e.printStackTrace();
            log.info("未知异常:{}", e);
            return APIResult.create(ErrorCodeEnum.SYSTEM_EXCEPTION);
        }

    }

    @Override
    public APIResult<String> uploadResume(File file, String fileName) {

        if (file==null){
            log.info("file不能为null");
            return APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        if (StringUtils.isNullOrEmpty(fileName)){
            log.info("fileName不能为空");
            return APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        String upToken = auth.uploadToken(bucket);
        String localTempDir = Paths.get(file.getParent(), bucket).toString();
        try {
            //设置断点续传文件进度保存目录
            FileRecorder fileRecorder = new FileRecorder(localTempDir);
            UploadManager uploadManager = new UploadManager(cfg, fileRecorder);
            Response response = uploadManager.put(file.getAbsolutePath(), fileName, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            log.info("上传成功，本地文件名:{}，返回信息:{}", fileName, domain + putRet.key);
            return APIResult.create(domain + putRet.key);
        } catch (QiniuException ex) {
            Response r = ex.response;
            log.info("上传失败，错误信息:{}", r.toString());
            return APIResult.create(Integer.toString(r.statusCode), r.toString());
        } catch (IOException e) {
            e.printStackTrace();
            log.info("未知异常:{}", e);
            return APIResult.create(ErrorCodeEnum.SYSTEM_EXCEPTION);
        }
    }

    @Override
    public APIResult<String> uploadByFecth(String url) {
        if (StringUtils.isNullOrEmpty(url)){
            log.info("url不能为空");
            return APIResult.create(ErrorCodeEnum.NOT_NULL);
        }
        String key = UUID.randomUUID().toString().toUpperCase() + url.substring(url.lastIndexOf("."));
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            FetchRet fetchRet = bucketManager.fetch(url, bucket, key);
            log.info("上传成功，资源url:{}，返回信息:{}", url,domain+fetchRet.key);
            return APIResult.create(domain + fetchRet.key);
        } catch (QiniuException ex) {
            Response r = ex.response;
            log.info("上传失败，错误信息:{}", r.toString());
            return APIResult.create(Integer.toString(r.statusCode), r.toString());
        }
    }


    @Override
    public APIResult<String> uploadByFecth(String url, String fileName) {

        if (url==null){
            log.info("url不能为null");
            return APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        if (StringUtils.isNullOrEmpty(fileName)){
            log.info("fileName不能为空");
            return APIResult.create(ErrorCodeEnum.NOT_NULL);
        }

        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            FetchRet fetchRet = bucketManager.fetch(url, bucket, fileName);
            log.info("上传成功，资源url:{}，返回信息:{}", url,domain+fetchRet.key);
            return APIResult.create(domain + fetchRet.key);
        } catch (QiniuException ex) {
            Response r = ex.response;
            log.info("上传失败，错误信息:{}", r.toString());
            return APIResult.create(Integer.toString(r.statusCode), r.toString());
        }
    }

    @Override
    public APIResult<String> getUploadToken() {
        String upToken = auth.uploadToken(bucket);
        return APIResult.create(upToken);
    }

    @Override
    public APIResult<String> sign(String url) {
        String finalUrl = url;
        if (!isOpen){
            long expireInSeconds = 3600;
            finalUrl = auth.privateDownloadUrl(url, expireInSeconds);
        }
        return APIResult.create(finalUrl);
    }

    @Override
    public APIResult<String> sign(String url, Long expireInSeconds) {
        String finalUrl = url;
        if (!isOpen){
            finalUrl = auth.privateDownloadUrl(url, expireInSeconds);
        }
        return APIResult.create(finalUrl);
    }
}
